package com.deimos.sps;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.vast.ows.OWSException;
import org.vast.util.DateTimeFormat;
import org.vast.util.TimeInfo;

import com.deimos.dataBase.Segment;
import com.deimos.dataBase.Task;
import com.deimos.dataBase.TaskController;
import com.spotimage.eosps.GetSensorAvailabilityRequest;
import com.spotimage.eosps.GetSensorAvailabilityResponse;

public class GetSensorAvailability {
    GetSensorAvailabilityRequest request = null;
    GetSensorAvailabilityResponse response = null;
    Task task = null;
    SimpleDateFormat DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

    public GetSensorAvailability(GetSensorAvailabilityRequest request) {
	this.request = request;
    }

    public GetSensorAvailabilityResponse buildResponse() throws OWSException {
	String id = request.getSensorID();

	response = new GetSensorAvailabilityResponse();

	Date start = new Date();
	Date stop = new Date();
	this.toDate(request.getRequestPeriod(), start, stop);

	TaskController taskController = new TaskController();
	List<Segment> segments = taskController.sensorsInUse(id, start, stop);
	List<TimeInfo> periods = new ArrayList<TimeInfo>();
	response.setResponsePeriod(request.getRequestPeriod());

	List<TimeInfo> unavailabilities = null;
	try {
	    unavailabilities = mergetSensorUnavaibilities(segments, response.getResponsePeriod());
	} catch (ParseException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}

	TimeInfo period = null;

	// first period
	if (unavailabilities != null && unavailabilities.size() > 0) {
	    period = new TimeInfo();
	    period.setTimeZone(response.getResponsePeriod().getTimeZone());

	    if (unavailabilities.get(0).getStartTime() < response.getResponsePeriod().getStartTime()) {
		period.setStartTime(unavailabilities.get(0).getStopTime());
		if (unavailabilities.size() > 1) {
		    period.setStopTime(unavailabilities.get(1).getStartTime());
		} else {
		    period.setStopTime(response.getResponsePeriod().getStopTime());
		}
	    } else {
		period.setStartTime(response.getResponsePeriod().getStartTime());
		period.setStopTime(unavailabilities.get(0).getStartTime());
	    }

	    periods.add(period);
	} else {
	    period = response.getResponsePeriod();
	    periods.add(period);
	}

	for (int i = 0; unavailabilities != null && i < unavailabilities.size(); i++) {
	    if (i == unavailabilities.size() - 1 && unavailabilities.get(i).getStopTime() < response.getResponsePeriod().getStopTime()) {
		period = new TimeInfo();
		period.setTimeZone(response.getResponsePeriod().getTimeZone());
		period.setStartTime(unavailabilities.get(i).getStopTime());
		period.setStopTime(response.getResponsePeriod().getStopTime());
		periods.add(period);
	    } else if (unavailabilities.get(i).getStopTime() < response.getResponsePeriod().getStopTime()) {
		period = new TimeInfo();
		period.setTimeZone(response.getResponsePeriod().getTimeZone());
		period.setStartTime(unavailabilities.get(i).getStopTime());
		period.setStopTime(unavailabilities.get(i + 1).getStartTime());
		periods.add(period);
	    }
	}

	response.setAvailabilityPeriods(periods);
	response.setVersion("2.0.0");
	response.setService("EOSPS");
	return response;
    }

    public List<TimeInfo> mergetSensorUnavaibilities(List<Segment> segments, TimeInfo responseTime) throws ParseException {
	List<TimeInfo> unavailabilities = new ArrayList<TimeInfo>();

	for (Segment segment : segments) {
	    TimeInfo time = new TimeInfo();
	    //time.setTimeZone(responseTime.getTimeZone());
	    //time.setBaseTime(responseTime.getBaseTime());
	    //time.setBaseAtNow(true);
	    
	    time.setStartTime(DateTimeFormat.parseIso(this.DATEFORMAT.format(segment.getBeginDate())));
	    time.setStopTime(DateTimeFormat.parseIso(this.DATEFORMAT.format(segment.getEndDate())));
	    System.out.println(segment.getBeginDate());
	    System.out.println(segment.getEndDate());
	    
	    unavailabilities.add(time);
	}

	for (TimeInfo time : unavailabilities) {
	    boolean intercept = false;
	    do {
		intercept = false;
		for (TimeInfo time2 : unavailabilities) {
		    if (time.intersects(time2) && time != time2) {
			if (time.getStartTime() > time2.getStartTime()) {
			    time.setStartTime(time2.getStartTime());
			}
			if (time.getStopTime() < time2.getStopTime()) {
			    time.setStopTime(time2.getStopTime());
			}
			intercept = true;
			unavailabilities.remove(time2);
		    }
		}
	    } while (intercept);
	}

	try {
	    sortSensorUnavaibilities((TimeInfo[]) unavailabilities.toArray(), 0, unavailabilities.size() - 1);
	} catch (Exception ex) {
	}
	return unavailabilities;
    }

    void sortSensorUnavaibilities(TimeInfo[] unavailabilities, int primero, int ultimo) {
	int i = primero, j = ultimo;
	TimeInfo pivote = unavailabilities[(primero + ultimo) / 2];
	TimeInfo auxiliar;

	do {
	    while (unavailabilities[i].getStartTime() < pivote.getStartTime())
		i++;
	    while (unavailabilities[j].getStartTime() > pivote.getStartTime())
		j--;

	    if (i <= j) {
		auxiliar = unavailabilities[j];
		unavailabilities[j] = unavailabilities[i];
		unavailabilities[i] = auxiliar;
		i++;
		j--;
	    }

	} while (i <= j);

	if (primero < j)
	    sortSensorUnavaibilities(unavailabilities, primero, j);
	if (ultimo > i)
	    sortSensorUnavaibilities(unavailabilities, i, ultimo);
    }

    public void toDate(TimeInfo date, Date start, Date stop) {
	try {

	    start.setTime(DATEFORMAT.parse(DateTimeFormat.formatIso(date.getStartTime(), date.getTimeZone())).getTime());
	    stop.setTime(DATEFORMAT.parse(DateTimeFormat.formatIso(date.getStopTime(), date.getTimeZone())).getTime());
	} catch (ParseException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
    }

}
